<?php
class WithdrawalSubmission extends DataExtension {
	public static function get_extra_config($class, $extension, $args) {
        return array(
            'db' => array(
                'ProcessDate' => 'SS_Datetime',
		        'Amount' => 'Currency',
		        'Status' => "Enum(array('Pending', 'Approved', 'Rejected', 'Canceled'), 'Pending')",
		        'Remark' => 'Varchar(250)'
            ),
            'has_one' => array(
		        'Admin' => 'Member',
		        'Member' => 'Member',
		        'PayoutMethod' => 'PayoutMethod'
            ),
            'many_many' => array(
                'Accounts' => Config::inst()->get($extension, $class)
            ),
            'searchable_fields' => array(
                'Created' => array(
					'field' => 'DateField',
					'filter' => 'DateMatchFilter'
				),
				'ProcessDate' => array(
					'field' => 'DateField',
					'filter' => 'DateMatchFilter'
				),
		        'PayoutMethod.Reference',
		        'Member.Username',
		        'Member.FirstName',
		        'Member.Surname',
		        'PayoutMethod.Amount' => array(
		            'filter' => 'GreaterThanOrEqualFilter'
		        ),
		        'PayoutMethod.ProcessingFee' => array(
		            'filter' => 'GreaterThanOrEqualFilter'
		        ),
		        'Status'
            ),
            'summary_fields' => array(
                'Member.Username',
		        'Member.Name',
		        'Created.Nice',
		        'ProcessDate.Nice',
		        'PayoutMethod.Title',
		        'PayoutMethod.Reference',
		        'PayoutMethod.Amount',
		        'PayoutMethod.ProcessingFee',
		        'Status',
		        'Admin.Username'
            ),
            'defaults' => array('Status' => 'Pending'),
            'default_sort' => 'Created DESC, ID DESC',
            'create_table_options' => array('MySQLDatabase' => 'ENGINE=InnoDB')
        );
    }

	function updateFieldLabels(&$labels) {
		$labels['Created'] = _t('WithdrawalSubmission.SUBMIT_ON', 'Submit On');
		$labels['Created.Nice'] = _t('WithdrawalSubmission.SUBMIT_ON', 'Submit On');
		$labels['ProcessDate'] = _t('WithdrawalSubmission.PROCESS_ON', 'Process On');
		$labels['ProcessDate.Nice'] = _t('WithdrawalSubmission.PROCESS_ON', 'Process On');
		$labels['Amount'] = _t('WithdrawalSubmission.AMOUNT', 'Amount');
		$labels['PayoutMethod.Amount'] = _t('WithdrawalSubmission.AMOUNT', 'Amount');
		$labels['Status'] = _t('WithdrawalSubmission.STATUS', 'Status');
		$labels['Remark'] = _t('WithdrawalSubmission.REMARK', 'Remark');
		$labels['PayoutMethod.Title'] = _t('WithdrawalSubmission.METHOD', 'Method');
		$labels['PayoutMethod.Reference'] = _t('WithdrawalSubmission.REFERENCE', 'Reference');
		$labels['PayoutMethod.ProcessingFee'] = _t('WithdrawalSubmission.PROCESSING_FEE', 'Processing Fee');
		$labels['Admin.Username'] = _t('WithdrawalSubmission.UPDATED_BY', 'Updated By');
		$labels['Member.Username'] = _t('WithdrawalSubmission.USERNAME', 'Username');
		$labels['Member.Name'] = _t('WithdrawalSubmission.NAME', 'Name');
		$labels['Member.FirstName'] = _t('WithdrawalSubmission.FIRSTNAME', 'First Name');
		$labels['Member.Surname'] = _t('WithdrawalSubmission.SURNAME', 'Surname');
	}

	function populateDefaults() {
        $this->owner->Status = 'Pending';
    }
    
    function validate(ValidationResult $validationResult) {
    	if($this->owner->SetUsername && !$this->owner->MemberID){
			$this->owner->MemberID = Distributor::get_id_by_username($this->owner->SetUsername);
		}
		
    	if(!$this->owner->MemberID) {
            $subvalid = new ValidationResult();
            $subvalid->error(_t('WithdrawalSubmission.INVALID_MEMBER_ID', 'Invalid member id'), 'INVALID_MEMBER_ID');
            $validationResult->combineAnd($subvalid);
        }

		if(!$this->owner->ID && $this->owner->Amount <= 0){
			$subvalid = new ValidationResult();
            $subvalid->error(_t('WithdrawalSubmission.INVALID_WITHDRAWAL_AMOUNT', "Invalid withdrawal amount"), "INVALID_WITHDRAWAL");
            $validationResult->combineAnd($subvalid);
		} else {
	        if(!$this->owner->ID && $this->owner->Amount) {
	            $minimum_withdrawal = $this->owner->config()->minimum_withdraw;
	            if($minimum_withdrawal > 0 && $minimum_withdrawal > $this->owner->Amount){
	                $subvalid = new ValidationResult();
	                $subvalid->error(_t('WithdrawalSubmission.NOT_EXCEED_MINIMUM_WITHDRAWAL', 'Minimum withdrawal amount is {minimum_withdrawal_amount}', 'Display not exceed minimum withdrawal amount', array('minimum_withdrawal_amount' => DBField::create_field('Currency', $minimum_withdrawal)->Nice())), 'MINIMUM_WITHDRAWAL');
	                $validationResult->combineAnd($subvalid);
	            }
				$account_class = $this->getAccountClass();
	            $balance = Account::get($account_class, $this->owner->MemberID)->Balance;
	            if($this->owner->Amount > $balance){
	                $subvalid = new ValidationResult();
	                $subvalid->error(_t('WithdrawalSubmission.INSUFFICIENT_BALANCE', 'Insufficient account balance ({balance})', 'Display insufficient account balance', array('balance' => DBField::create_field('Currency', $balance)->Nice())), "INSUFFICIENT_ACCOUNT_BALANCE");
	                $validationResult->combineAnd($subvalid);
	            }
				
				$maximum_withdrawal = $this->owner->config()->maximum_withdraw;
				if($maximum_withdrawal > 0 && $this->owner->Amount > $maximum_withdrawal){
	                $subvalid = new ValidationResult();
	                $subvalid->error(_t('WithdrawalSubmission.EXCEED_MAXIMUM_WITHDRAWAL', 'Maximum withdrawal amount is {maximum_withdrawal_amount}', 'Display exceed maximum withdrawal amount', array('maximum_withdrawal_amount' => DBField::create_field('Currency', $maximum_withdrawal)->Nice())), 'MAXIMUM_WITHDRAWAL');
	                $validationResult->combineAnd($subvalid);
	            }
	        }
		}

        return $validationResult;
    }

	function getCMSFields() {
        $fields = parent::getCMSFields();
        if($this->exists()){
            $fields = FieldList::create(
                 LiteralField::create('Statement', $this->ViewHTML())
            );
        }
        
        return $fields;
    }
    
    function getWithdrawFormFields($memberid){
    	$account_class = $this->getAccountClass();
    	$minimum_withdraw = $this->owner->config()->minimum_withdraw;
		$maximum_withdraw = $this->owner->config()->maximum_withdraw;
        $fields = FieldList::create(
        	HiddenField::create('MemberID', 'MemberID', $memberid),
            HiddenField::create('AccountBalance', 'AccountBalance', Account::get($account_class, $memberid)->Balance),
            HiddenField::create('AccountClass', 'AccountClass', $account_class),
            HtmlEditorField_Readonly::create('ShowAccountBalance', _t('WithdrawalSubmission.CURRENT_BALANCE', 'Current Balance'), Account::get($account_class, $memberid)->obj('Balance')->Nice())
        );
		
		if($this->owner->config()->use_dropdown){
			$withdraw_range = $this->owner->config()->withdraw_range;
			$fields->push(WithdrawalAmountDropdownField::create('Amount', _t('WithdrawalSubmission.WITHDRAWAL_AMOUNT', 'Withdrawal Amount'))->setMinimumWithdrawal($minimum_withdraw)->setMaximumWithdrawal($maximum_withdraw)->setWithdrawalRange($withdraw_range));
		}
		else {
	        if($minimum_withdraw > 0 && $maximum_withdraw > 0){
	            if($minimum_withdraw > Account::get($account_class, $memberid)->Balance){
	                $msg = sprintf('<b style="color: red">%s - %s</b>', DBField::create_field('Currency', $minimum_withdraw)->Nice(), DBField::create_field('Currency', $maximum_withdraw)->Nice());
	            }
	            else{
	                $msg = sprintf('<b style="color: green">%s - %s</b>', DBField::create_field('Currency', $minimum_withdraw)->Nice(), DBField::create_field('Currency', $maximum_withdraw)->Nice());
	            }
	            $fields->push(HtmlEditorField_Readonly::create('ShowWithdrawRange', _t('WithdrawalSubmission.WITHDRAWAL_RANGE', 'Withdrawal Range'), $msg));
	        }
			else if($minimum_withdraw > 0){
	            if($minimum_withdraw > Account::get($account_class, $memberid)->Balance){
	                $msg = sprintf('<b style="color: red">%s</b>', DBField::create_field('Currency', $minimum_withdraw)->Nice());
	            }
	            else{
	                $msg = sprintf('<b style="color: green">%s</b>', DBField::create_field('Currency', $minimum_withdraw)->Nice());
	            }
	            $fields->push(HtmlEditorField_Readonly::create('ShowMinimumWithdraw', _t('WithdrawalSubmission.MINIMUM_WITHDRAWAL', 'Minimum Withdrawal'), $msg));
	        }
			else if($maximum_withdraw > 0){
	            $msg = sprintf('<b style="color: red">%s</b>', DBField::create_field('Currency', $maximum_withdraw)->Nice());
	            $fields->push(HtmlEditorField_Readonly::create('ShowMaximumWithdraw', _t('WithdrawalSubmission.MAXIMUM_WITHDRAWAL', 'Maximum Withdrawal'), $msg));
	        }
			
			$fields->push(WithdrawalAmountField::create('Amount', _t('WithdrawalSubmission.WITHDRAWAL_AMOUNT', 'Withdrawal Amount'))->setMinimumWithdrawal($minimum_withdraw)->setMaximumWithdrawal($maximum_withdraw));
		}
        
        $fields = PayoutMethod::combined_form_fields($fields, $memberid);
        
        $this->owner->extend('updateWithdrawFormFields', $fields);
        
        return $fields;
    }
    
    function getWithdrawCancelFormFields(){
        $fields = FieldList::create(
            HiddenField::create('ID', 'ID', $this->owner->ID),
            HiddenField::create('Status', 'Status', 'Canceled'),
            TextField::create('Remark', _t('WithdrawalSubmission.REMARK', 'Remark'), $this->owner->Remark)
        );
        
        $this->owner->extend('updateWithdrawCancelFormFields', $fields);
        
        return $fields;
    }
    
    function onBeforeWrite(){
        if($this->owner->SetUsername){
            $this->owner->setField('MemberID', Distributor::get_id_by_username($this->owner->SetUsername));
        }
        
        if($this->owner->isChanged('Status') && $this->owner->Status != 'Pending'){
            $this->owner->setField('AdminID', Member::currentUserID())->setField('ProcessDate', SS_Datetime::now()->Rfc2822());
        }
    }

    function onAfterWrite(){
    	if($this->owner->isChanged('Status') && $this->owner->Amount > 0){
    		$account_class = $this->getAccountClass();
	        if($this->owner->Status == 'Pending'){
	        	if($this->owner->config()->join_statement){
	        		if(!$count = $this->owner->Accounts()->filter('Type', 'Withdrawal')->filter('Debit:GreaterThan', 0)->count()){
		                $data = array(
		                    'Type' => 'Withdrawal',
		                    'Debit' => $this->owner->Amount,
		                    'Reference' => $this->owner->PayoutMethod()->Reference,
		                    'Description' => 'Request for withdrawal'
		                );
						$id = $account_class::create_statement($data, $this->owner->MemberID);
		                $this->owner->Accounts()->add($id);
		            }
	        	}
				else{
		            if($this->owner->PayoutMethod()->Amount > 0 && !$count = $this->owner->Accounts()->filter('Type', 'Withdrawal')->filter('Debit:GreaterThan', 0)->count()){
		                $data = array(
		                    'Type' => 'Withdrawal',
		                    'Debit' => $this->owner->PayoutMethod()->Amount,
		                    'Reference' => $this->owner->PayoutMethod()->Reference,
		                    'Description' => 'Request for withdrawal'
		                );
						$id = $account_class::create_statement($data, $this->owner->MemberID);
		                $this->owner->Accounts()->add($id);
		            }
		            
		            if($this->owner->PayoutMethod()->ProcessingFee > 0 && !$count = $this->owner->Accounts()->filter('Type', 'Withdrawal Fee')->filter('Debit:GreaterThan', 0)->count()){
		                $data = array(
		                    'Type' => 'Withdrawal Fee',
		                    'Debit' => $this->owner->PayoutMethod()->ProcessingFee,
		                    'Reference' => $this->owner->PayoutMethod()->Reference,
		                    'Description' => 'Processing fee for withdrawal'
		                );
						$id = $account_class::create_statement($data, $this->owner->MemberID);
		                $this->owner->Accounts()->add($id);
		            }
	            }
	        }
	        
	        if($this->owner->Status == 'Rejected' || $this->owner->Status == 'Canceled'){
	            $withdrawStatements = $this->owner->Accounts()->filter('Type', 'Withdrawal')->filter('Debit:GreaterThan', 0);
	            if($withdrawStatements->count() > $this->owner->Accounts()->filter('Type', 'Withdrawal')->filter('Credit:GreaterThan', 0)->count()){
	                foreach($withdrawStatements as $withdrawStatement){
	                    $data = array(
	                        'Type' => $withdrawStatement->Type,
	                        'Credit' => $withdrawStatement->Debit,
	                        'Reference' => $withdrawStatement->Reference,
	                        'Description' => 'Refund - Request for withdrawal'
	                    );
						$id = $account_class::create_statement($data, $withdrawStatement->MemberID);
	                    $this->owner->Accounts()->add($id);
	                }
	            }
	            if($this->owner->PayoutMethod()->ProcessingFee > 0){
	                $withdrawStatements = $this->owner->Accounts()->filter('Type', 'Withdrawal Fee')->filter('Debit:GreaterThan', 0);
	                if($withdrawStatements->count() > $this->owner->Accounts()->filter('Type', 'Withdrawal Fee')->filter('Credit:GreaterThan', 0)->count()){
	                    foreach($withdrawStatements as $withdrawStatement){
	                        $data = array(
	                            'Type' => $withdrawStatement->Type,
	                            'Credit' => $withdrawStatement->Debit,
	                            'Reference' => $withdrawStatement->Reference,
	                            'Description' => 'Refund - Processing fee for withdrawal'
	                        );
							$id = $account_class::create_statement($data, $withdrawStatement->MemberID);
	                        $this->owner->Accounts()->add($id);
	                    }
	                }
	            }
	        }
	    }
    }
	
	function getType(){
		return singleton($this->getAccountClass())->i18n_singular_name();
	}
	
	function getAccountClass(){
		return Config::inst()->get($this->class, $this->owner->class);
	}
    
    function getFullDetailHTML() {
        $this->owner->Format = 'HTML';
		$this->owner->PayoutMethod()->Format = 'HTML';
		$template_ss = $this->owner->config()->detail_template ? $this->owner->config()->detail_template : 'WithdrawStatementDetail';
        $template = new SSViewer($template_ss);
        $template->includeRequirements(false);
        return $this->owner->renderWith($template);
    }
    
    function ViewHTML(){
        $template_ss = $this->owner->config()->statement_template ? $this->owner->config()->statement_template : 'WithdrawStatementTemplate';
        $this->owner->PrintTime = SS_Datetime::now()->Nice();
        $this->owner->Format = 'HTML';
		$this->owner->PayoutMethod()->Format = 'HTML';
        $this->owner->SiteConfig = SiteConfig::current_site_config();
        $template = new SSViewer($template_ss);
        $template->includeRequirements(false);
        return $this->owner->renderWith($template);
    }
    
    function ViewPDF(){
    	if($this->owner->config()->allowed_pdf && class_exists('SS_DOMPDF')){
	        $template_ss = $this->owner->config()->statement_template ? $this->owner->config()->statement_template : 'WithdrawStatementTemplate';
	        $this->owner->PrintTime = SS_Datetime::now()->Nice();
	        $this->owner->Format = 'PDF';
			$this->owner->PayoutMethod()->Format = 'PDF';
	        $this->owner->SiteConfig = SiteConfig::current_site_config();
	        $template = new SSViewer($template_ss);
	        $template->includeRequirements(false);
			$pdf = new SS_DOMPDF();
			$pdf->setHTML($this->owner->renderWith($template));
			$pdf->render();
			return $pdf->stream(sprintf('withdrawal_%s.pdf', $this->owner->PayoutMethod()->Reference));
		}
    }
    
    function ViewPrint(){
        $template_ss = $this->owner->config()->statement_template ? $this->owner->config()->statement_template : 'WithdrawStatementTemplate';
        $this->owner->PrintTime = SS_Datetime::now()->Nice();
        $this->owner->Format = 'PRINT';
		$this->owner->PayoutMethod()->Format = 'PRINT';
        $this->owner->SiteConfig = SiteConfig::current_site_config();
        $template = new SSViewer($template_ss);
        $template->includeRequirements(false);
        return $this->owner->renderWith($template);
    }
}
?>